/**
 * 模板相关
 */
Rsd.define('Rsd.common.Template', {
    extend:'Rsd.common.Object',
    tplRenders: {}, 
    /**
     * 数据缓存
     */
    data:{},
    /*
    * */
    constructor: function Template(config) {
        //debugger;
        this.apply(config);
    },
    
    /**
     * 渲染所有模板，在不指定数据源的情况下，使用全局数据源渲染
     * @param {*} gblData 全局数据 
     */
    tplAll:function tplAll(gblData, callback) {
        var me = this;
        me.tpl('[rsd-tpl]', gblData, callback); 
    },

    /**
     * 处理 dom
     * @param {*} selector 
     */
    tpl :function tpl(selector, gblData, callback) {
        var me = this;
        var doms = Rsd.select(selector);

        var __fn__ = function (tpl_dom) {
            var nodes = tpl_dom.childNodes;
            var _del_nodes = [];
            for (var i = 0; i < nodes.length; i++) {
                var node = tpl_dom.childNodes[i];

                if (node.tagName == undefined) {
                    _del_nodes.push(node);
                    continue;
                }
                //console.log(node.tagName);
                if (node.tagName == 'TITLE') {
                    document.title = node.innerText;
                    _del_nodes.push(node);
                }

                if (node.tagName == 'LINK') {
                    //不需要处理，可以生效
                }

                if (node.tagName == 'SCRIPT') {
                    //js 添加到 dom 后，未执行，需要重新添加
                    //console.log(node.src);
                    var script = document.createElement('script');
                    if (node.src) {
                        script.src = node.src;
                    }
                    if (node.innerText) {
                        //console.log(node.innerText);
                        script.innerText = node.innerText;
                    }
                    if (node.async) {
                        script.async = true;
                    }
                    script.onload = function () {
                        if (this.src) {
                            //console.log(this.src);
                        }
                        else {
                            console.log(this.innerText);
                        }

                    };
                    try {
                        document.body.appendChild(script);
                        _del_nodes.push(node);
                    }
                    catch (err) {
                        console.error(err);
                        console.error(script);
                    }

                    continue;
                }
            }

            for (var i in _del_nodes) {
                tpl_dom.removeChild(_del_nodes[i]);
            }
        };

        var _renderFn_ = function (dom, index) {
            //var dom = dom;
            var tplItem = { element: dom, file: '', index: index, total: doms.length };

            var _fn = function () {
                var _dom = this.element;
                setTimeout(function () {

                    var tplFile = _dom.getAttribute('rsd-tpl');
                    if (Rsd.isEmpty(tplFile)) {
                        console.error('rsd-tpl value is empty');
                        return;
                    }
                    tplItem.file = tplFile;
                    //是模板 路径
                    var isTpl = me.isTplFilePath(tplFile.toLocaleLowerCase());

                    //指定数据源
                    var datasourceId = _dom.getAttribute('rsd-ds');
                    if (datasourceId) {
                        //使用全局数据源 指定子集数据渲染
                        if (gblData[datasourceId]) {
                            if (isTpl) {
                                //通过模板文件渲染
                                me.templateFromFile(tplFile).render(_dom, gblData[datasourceId]);
                                if (callback) {
                                    callback.apply(me, [tplItem, gblData[datasourceId]]);
                                }
                            }
                            else {
                                //通过<script>模板块 渲染
                                me.templateFromScript(tplFile).render(_dom, gblData[datasourceId]);
                                if (callback) {
                                    callback.apply(me, [tplItem, gblData[datasourceId]]);
                                }
                            }
                            //修正 不同dom标签
                            __fn__(_dom);
                            return;
                        }

                        //使用服务端数据源
                        me.getDataSource(datasourceId, function (_data) {
                            if (isTpl) {
                                //通过模板文件渲染
                                me.templateFromFile(tplFile).render(_dom, _data);
                                if (callback) {
                                    callback.apply(me, [tplItem, _data]);
                                }
                            }
                            else {
                                //通过<script>模板块 渲染
                                me.templateFromScript(tplFile).render(_dom, _data);
                                if (callback) {
                                    callback.apply(me, [tplItem, _data]);
                                }

                            }
                            //修正 不同dom标签
                            __fn__(_dom);
                        });

                        return;
                    }

                    //未指定 数据源=>使用全局数据源渲染
                    if (isTpl) {
                        //通过模板文件渲染
                        me.templateFromFile(tplFile).render(_dom, gblData);
                        if (callback) {
                            callback.apply(me, [tplItem, gblData]);
                        }
                    }
                    else {
                        //通过<script>模板块 渲染
                        me.templateFromScript(tplFile).render(_dom, gblData);
                        if (callback) {
                            callback.apply(me, [tplItem, gblData]);
                        }
                    }
                    //修正 不同dom标签
                    __fn__(_dom);
                    return;

                }, 0);
            };

            _fn.call(tplItem);
        }

        doms.map(_renderFn_);

    },

    /**
     * 
     * @param {*} str 
     * @returns 
     */
    isTplFilePath:function isTplFilePath(str) {
        return str.endWith('.tpl')
    },
    /**
     * @description 通过页面body中的任意位置定义<script>{模版内容}</script>来构建模板
     * @param {*} scriptId  模板存在<script id="tpl_banner" name="banner" schema="schema/banner.json"></script>标签中
     * @returns 
     */
    templateFromScript:function templateFromScript(scriptId, callback) {
        var me = this;
        var renderDom = function (selector, data) { };
        var key = scriptId;
        if (me.tplRenders[key]) {
            renderDom = me.tplRenders[key].fn;
        }
        else {
            //从页面内容中获取模板
            var script = document.getElementById(scriptId);
            //console.log(script);
            if (script) {
                renderDom = me.getRenderFn(script.innerHTML);

                //通过 id, 缓存该 编译器方法 
                if (!me.tplRenders[key]) {
                    me.tplRenders[key] = { fn: renderDom, args: [] };
                }
                //删除  dom 
                script.parentNode.removeChild(script);

            }
        }

        if (callback) {
            callback.apply(me, [renderDom]);
        }
        //console.debug(tplDoms[0].innerHTML);  

        //返回渲染对象    
        return { key: key, name: script.getAttribute('name'), schema: script.getAttribute('schema'), render: renderDom };
    },

    /**
     * @description 通过模板文件来构建模板
     * @param {*} tplSelector 
     * @param {*} callback 
     * @returns 
     */
    templateFromFile: function templateFromFile(tplFile, callback) {
        var me = this;
        var renderDom = null;

        //是模板文件路径
        var key = tplFile.toLocaleLowerCase();
        if (!me.tplRenders[key]) {
            me.tplRenders[key] = { args: [], fn: null };
        }

        if (me.tplRenders[key].fn) {
            //模板已缓存
            renderDom = me.tplRenders[key].fn;
        }
        else {
            //模板未加载 
            renderDom = function (selector, data) {

                if (arguments.length != 2) {
                    throw Error('render arguments length must be 2.');
                }

                if (me.tplRenders[key].fn) {
                    me.tplRenders[key].fn.apply(me, [selector, data]);
                }
                else {
                    //记录在编译完成前 请求的 方法的参数
                    me.tplRenders[key].args.push([selector, data]);
                }

            }
        }

        var _callback = function (_render) {

            me.tplRenders[key].fn = _render;

            var args = me.tplRenders[key].args;

            for (var i in args) {
                _render.apply(me, args[i]);
            }

            me.tplRenders[key].args = [];

            if (callback) {
                callback.apply(me, [_render]);
            }

        }

        me.loadTemplateFile(tplFile, _callback);

        //返回渲染对象
        return { key: tplFile, name: '', schema: tplFile.replace('section/', 'schema/').replace('.tpl', '.json'), render: renderDom }; 
    },

    /**
     * 
     * @param {*} url 
     */
    loadTemplateFile:function loadTemplateFile(url, callback) {
        var me = this;
        var key = url.toLocaleLowerCase();
        if (me.tplRenders[key] && me.tplRenders[key].fn) {
            me.tplRenders[key];
            //处理回调
            if (callback) {
                callback.apply(me, [me.tplRenders[key].fn]);
            }
        }

        Rsd.loadTemplateFile(url, function (tplStr) {
            //console.debug(url);
            //console.debug(tplStr);

            var _render = me.getRenderFn(tplStr);
            //console.debug(render);

            //缓存 编译方法
            if (me.tplRenders[key]) {
                me.tplRenders[key].fn = _render;
            }
            else {
                me.tplRenders[key] = { fn: _render, args: [] };
            }
            //处理回调
            if (callback) {
                callback.apply(me, [_render]);
            }
        });
    },

    /**
     * 
     */
    getRenderFn:function getRenderFn(tplStr) {
        var me = this;
        var compiler = Rsd.compile(tplStr);
        //console.log(compiler); 
        var renderHtml = compiler.fn;
        //console.debug(render);
        if (!renderHtml) {
            renderHtml = function () { return ""; };
        }

        var _render = function _renderDom(selector, data) {

            var html = renderHtml(data);
            if (Rsd.isEmpty(html)) {
                console.error('no html');
                return;
            }
            var doms = [];
            if (Rsd.isString(selector)) {
                doms = Rsd.select(selector);
            }
            else {
                doms.push(selector);
            }

            for (var i in doms) {
                doms[i].innerHTML = html;
            }

        };

        return _render;
    },

    /***
      * 获取 【页面模块】数据源，主要用于加载动态数据部分
      */
    getDataSource:function getDatasource(datasourceId, callback) {
        console.debug('从服务端获取数据源：' + datasourceId);
        var me = this;
        //从json文件获取
        if (datasourceId.endWith('.json')) {
            Rsd.loadJsonFile(datasourceId, function (data) {

                //console.log(data);
                var _data = data;
                if (data) {
                    me.data[datasourceId] = _data;
                }

                if (callback) {
                    callback.apply(me, [_data]);
                }

            });

            return;
        }

        //从 api service 获取
        me.requestService(me.getDataSourceServiceName, { Id: datasourceId }, function (resp) {
            //console.log(resp);
            if (resp.success) {
                var _data = resp.data;
                if (_data) {
                    me.data[datasourceId] = _data;
                }

                if (callback) {
                    callback.apply(me, [_data]);
                }
            }


        });

    },

    /**
     * 从json文件或服务端 加载【页面数据】，主要用户加载页面静态数据
     * @param {*} serviceName 
     * @param {*} callback 
     * @returns 
     */
    loadData :function loadData(pageName, callback) {
        var me = this;
        var _pageName = pageName;
        if (Rsd.isEmpty(pageName)) {
            _pageName = Rsd.encodeURI(document.location.href);
        }

        if (pageName.endWith('.json')) {
            Rsd.loadJsonFile(_pageName, function (data) {

                //console.log(data);  
                if (callback) {
                    callback.apply(this, [data]);
                }

            });

            return;
        }
        //从 服务端加载
        this.requestService(this.loadDataServiceName, { page: _pageName }, function (resp) {

            if (resp.success) {
                var _data = resp.data;
                if (_data) {
                    me.data = _data;
                }
                if (callback) {
                    callback.apply(this, [_data]);
                }
            }

        });

    },

    /**
     * @description 渲染当前页面：将将数据和模板中的dom元素渲染到当前页面上
     * master文件 格式：
     * <rsd-head></rsd-head>
     * <rsd-body>
     * <slot name="content"></slot>
     * </rsd-body>
     * @param {*} data 
     * @param {*} master 模板文件地址，非必填，为空时，从html 标签中获取属性data-master值
     */
    pageInit :function pageInit(data, master) {

        var _data = data || {};
        //渲染master模板
        var _master = master;
        if (!_master) {
            //获取模板文件地址
            _master = document.getElementsByTagName('html')[0].getAttribute('data-master');
        }

        if (_master) {
            Rsd.loadTemplateFile(_master, function (str) {

                //console.log('已加载master模板');

                var _appendFn = function (html) {

                    var nodes = Rsd.toHtml(html);
                    //console.log('append master dom')
                    for (var i = 0; i < nodes.length; i++) {
                        var node = nodes[i];
                        if (!node.tagName) {
                            continue;
                        }
                        if (node.tagName == 'RSD-HEAD') {
                            for (var j = 0; j < node.childNodes.length; j++) {
                                if (!node.childNodes[j].tagName) {
                                    continue;
                                }
                                //console.log(node.childNodes[j].tagName)
                                if (node.childNodes[j].tagName == 'SCRIPT') {
                                    //body.appendChild(node.childNodes[j]);
                                    var script = document.createElement('script');
                                    if (node.childNodes[j].src) {
                                        script.src = node.childNodes[j].src;
                                    }
                                    if (node.childNodes[j].innerText) {
                                        script.innerText = node.childNodes[j].innerText;
                                    }
                                    if (node.childNodes[j].async) {
                                        script.async = true;
                                    }
                                    script.onload = function () {
                                        console.log(this.src);
                                    };
                                    document.head.appendChild(script);
                                    continue;

                                }
                                document.head.appendChild(node.childNodes[j]);
                            }
                            continue;
                        }
                        if (node.tagName == 'RSD-BODY') {

                            for (var j = 0; j < node.childNodes.length; j++) {
                                if (!node.childNodes[j].tagName) {
                                    continue;
                                }
                                //console.log(node.childNodes[j].tagName)
                                if (node.childNodes[j].tagName == 'SCRIPT') {
                                    //body.appendChild(node.childNodes[j]);
                                    var script = document.createElement('script');
                                    if (node.childNodes[j].src) {
                                        script.src = node.childNodes[j].src;
                                    }
                                    if (node.childNodes[j].innerText) {
                                        script.innerText = node.childNodes[j].innerText;
                                    }
                                    if (node.childNodes[j].async) {
                                        script.async = true;
                                    }
                                    script.onload = function () {
                                        //console.log(this.src);
                                    };
                                    document.body.appendChild(script);
                                    continue;
                                }
                                document.body.appendChild(node.childNodes[j]);
                            }
                            continue;
                        }
                    }

                };

                var renderFn = Rsd.compile(str);
                //console.log(renderFn);

                var html = renderFn(_data);
                //console.log(html);

                _appendFn(html);


            });
        }
        else {
            console.error('html 标签未设置属性：data-master');
        }

        //使用当前页面中的dom元素，替换模版页面中的slot标签
        window.onload = function () {
            var _soltContentNodes = Rsd.select(document.body, "[slot]");
            //console.log(_soltContentNodes);
            var _soltNodes = Rsd.select(document.body, "slot");
            //console.log(_soltNodes);
            for (var i = 0; i < _soltContentNodes.length; i++) {
                var content = _soltContentNodes[i];

                for (var j = 0; j < _soltNodes.length; j++) {
                    var slot = _soltNodes[j];
                    //console.log(slot.name == content.slot,slot.name , content.slot);
                    if (slot.name == content.slot) {
                        slot.parentNode.appendChild(content);
                        //移除 slot
                        slot.parentNode.removeChild(slot);
                    }
                }

            }

        }

    }

},function(type){

});